---
layout: layouts/page.njk
title: Chart
description: Displays the path to the current resource using a hierarchy of links.
toc:
  - label: Usage
    id: usage
---
<div class="grid gap-6">
  <div class="grid grid-cols-2 gap-6">
    <div class="card">
      <header>
        <h2>Area Chart</h2>
        <p>Showing total visitors for the last 6 months</p>
      </header>
      <section>
        <canvas id="chart-area-default"></canvas>
      </section>
      <footer>
        <div class="grid gap-2 text-sm">
          <div class="flex items-center gap-2 leading-none font-medium">
            Trending up by 5.2% this month
            {% lucide "trending-up", { "class": "size-4" } %}
          </div>
          <div class="text-muted-foreground flex items-center gap-2 leading-none">January - June 2024</div>
        </div>
      </footer>
    </div>

    <div class="card">
      <header>
        <h2>Area Chart - Stacked</h2>
        <p>Showing total visitors for the last 6 months</p>
      </header>
      <section>
        <canvas id="chart-area-stacked"></canvas>
      </section>
      <footer>
        <div class="grid gap-2 text-sm">
          <div class="flex items-center gap-2 leading-none font-medium">
            Trending up by 5.2% this month
            {% lucide "trending-up", { "class": "size-4" } %}
          </div>
          <div class="text-muted-foreground flex items-center gap-2 leading-none">January - June 2024</div>
        </div>
      </footer>
    </div>

    <div class="card">
      <header>
        <h2>Bar Chart - Multiple</h2>
        <p>Showing total visitors for the last 6 months</p>
      </header>
      <section>
        <canvas id="chart-bar-multiple"></canvas>
      </section>
      <footer>
        <div class="grid gap-2 text-sm">
          <div class="flex items-center gap-2 leading-none font-medium">
            Trending up by 5.2% this month
            {% lucide "trending-up", { "class": "size-4" } %}
          </div>
          <div class="text-muted-foreground flex items-center gap-2 leading-none">January - June 2024</div>
        </div>
      </footer>
    </div>

    <div class="card">
      <header>
        <h2>Doughnut Chart</h2>
        <p>Showing total visitors for the last 6 months</p>
      </header>
      <section class="relative">
        <div>
          <div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-center">
            <div class="text-3xl font-semibold">1,125</div>
            <div class="text-muted-foreground text-xs">Visitors</div>
          </div>
          <canvas id="chart-doughnut" class="max-h-[200px] mx-auto"></canvas>
        </div>
      </section>
    </div>
  </div>

  <div class="card">
    <header>
      <h2>Bar Chart - Interactive</h2>
      <p>Showing total visitors for the last 6 months</p>
    </header>
    <section>
      <canvas id="chart-bar-interactive"></canvas>
    </section>
  </div>

  <div class="card">
    <header>
      <h2>Bar Chart - Interactive</h2>
      <p>Showing total visitors for the last 6 months</p>
    </header>
    <section class="max-h-[150px]">
      <canvas id="chart-line-interactive"></canvas>
    </section>
  </div>


<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

<script>
  // Helper function to MULTIPLY the alpha channel of oklch colors by a factor
  function setAlpha(colorString, alphaFactor) {
    colorString = colorString.trim();
    if (colorString.startsWith('oklch(')) {
      const match = colorString.match(/^oklch\(([^\)]+?)\s*(?:\/\s*([\d.]+)(%?)\s*)?\)$/);
      if (match && match[1]) {
        const lchPart = match[1];
        let currentAlpha = 1.0;

        if (match[2]) {
          currentAlpha = parseFloat(match[2]);
          if (match[3] === '%') {
            currentAlpha /= 100;
          }
        }

        let newAlpha = currentAlpha * alphaFactor;
        newAlpha = Math.max(0, Math.min(1, newAlpha)); 

        return `oklch(${lchPart} / ${newAlpha.toFixed(3)})`;
      } else {
        console.warn('Failed to parse oklch string:', colorString);
        return colorString;
      }
    }
    
    return colorString;
  }

  const computedStyle = getComputedStyle(document.documentElement);
  const themeColors = {
    background: computedStyle.getPropertyValue('--background').trim(),
    border: computedStyle.getPropertyValue('--border').trim(),
    mutedForeground: computedStyle.getPropertyValue('--muted-foreground').trim(),
    foreground: computedStyle.getPropertyValue('--foreground').trim(),
    chart1: computedStyle.getPropertyValue('--chart-1').trim(),
    chart2: computedStyle.getPropertyValue('--chart-2').trim(),
    chart3: computedStyle.getPropertyValue('--chart-3').trim(),
    chart4: computedStyle.getPropertyValue('--chart-4').trim(),
    chart5: computedStyle.getPropertyValue('--chart-5').trim(),
  };

  const getOrCreateTooltip = (chart) => {
    let tooltipEl = chart.canvas.parentNode.querySelector('div[role="tooltip"]');

    if (!tooltipEl) {
      const tooltipHTML = `
        <div
          role="tooltip" 
          class="border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl opacity-0 absolute pointer-events-none transition-all duration-400 space-y-1"
        >
          <h3 class="font-medium"></h3>
          <ul class="grid gap-1"></ul>
        </div>`;
      const parser = new DOMParser();
      const doc = parser.parseFromString(tooltipHTML.trim(), 'text/html');
      tooltipEl = doc.body.firstChild;
      chart.canvas.parentNode.appendChild(tooltipEl);
    }
    return tooltipEl;
  };

  const externalTooltipHandler = (context) => {
    const {chart, tooltip} = context;
    const chartType = chart.config._config.type;
    const tooltipEl = getOrCreateTooltip(chart);
    const titleEl = tooltipEl.querySelector('h3');
    const bodyEl = tooltipEl.querySelector('ul');

    // Hide if no tooltip
    if (tooltip.opacity === 0) {
      tooltipEl.classList.remove('opacity-100');
      tooltipEl.classList.add('opacity-0');
      return;
    }

    let bodyHtml = '';
    if (tooltip.body) {
      const titleLines = tooltip.title || [];
      const bodyLines = tooltip.body.map(b => b.lines);

      if (titleEl) {
        if (chartType === 'doughnut') {
          titleEl.remove();
        } else {
          titleEl.textContent = titleLines[0] || '';
        }
      } 

      bodyLines.forEach((body, i) => {
        const colors = tooltip.labelColors[i];
        const parts = body[0].split(': ');
        const label = chartType === 'doughnut'
          ? titleLines[0] || ''
          : parts[0] || '';
        const value = parts[1] || '';

        let color;
        switch (chartType) {
          case 'doughnut':
          case 'pie':
          case 'bar':
            color = colors.backgroundColor;
            break;
          default:
            color = colors.borderColor;
        }

        bodyHtml += `<li class="flex w-full flex-wrap items-center justify-between leading-none gap-x-2">
          <div class="flex items-center gap-x-1.5">
            <div class="shrink-0 rounded-[2px] size-2.5 block" style="background:${color}"></div>
            <span class="text-muted-foreground">${label}</span>
          </div>
          <span class="text-foreground font-medium font-mono tabular-nums">${value}</span>
        </li>`;
      });
    }
    
    if (bodyEl) bodyEl.innerHTML = bodyHtml;

    const {offsetLeft: positionX, offsetTop: positionY} = chart.canvas;
    const tooltipHeight = tooltipEl.offsetHeight;
    const tooltipWidth = tooltipEl.offsetWidth;
    const caretX = tooltip.caretX;
    const caretY = tooltip.caretY;
    const xAlign = tooltip.xAlign;
    const yAlign = tooltip.yAlign;
    const tooltipOffset = 8;

    let left = positionX + caretX;
    let top = positionY + caretY;

    if (xAlign === 'center') {
      left -= tooltipWidth / 2;
    } else if (xAlign === 'right') {
      left -= (tooltipWidth + tooltipOffset); 
    } else { // xAlign === 'left'
      left += tooltipOffset; 
    }

    if (yAlign === 'center') {
      top -= tooltipHeight / 2;
    } else if (yAlign === 'top') {
      top -= (tooltipHeight + tooltipOffset); 
    } else {
      top += tooltipOffset; 
    }
    
    const canvasBounds = chart.canvas.getBoundingClientRect();
    if (left < 0) {
      left = 0;
    } else if (left + tooltipWidth > canvasBounds.width) { 
      left = canvasBounds.width - tooltipWidth;
    } 
    if (top < 0) {
      top = 0;
    } else if (top + tooltipHeight > window.innerHeight) { 
       const flippedTop = positionY + caretY - tooltipHeight - tooltipOffset; 
       if (flippedTop >= 0) top = flippedTop;
    } 
    
    tooltipEl.classList.remove('opacity-0');
    tooltipEl.classList.add('opacity-100');
    tooltipEl.style.left = left + 'px';
    tooltipEl.style.top = top + 'px';
  };

  let ctx = document.getElementById('chart-area-default');
  let data = {
    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
    datasets: [{
      label: 'Desktop',
      data: [186, 305, 237, 73, 209, 214],
      borderWidth: 1,
      backgroundColor: setAlpha(themeColors.chart1, 0.2),
      borderColor: themeColors.chart1,
      pointRadius: 0,
      pointHoverRadius: 4,
      pointHoverBackgroundColor: themeColors.chart1,
      pointHoverBorderColor: themeColors.chart1,
      fill: 'origin'
    }]
  };
  let config = {
    type: 'line',
    data: data,
    options: {
      tension: 0.4,
      interaction: {
        mode: 'nearest',
        axis: 'x',
        intersect: false
      },
      scales: {
        y: {
          border: { display: false },
          grid: { 
            color: setAlpha(themeColors.border, 0.5),
            lineWidth: 1
          },
          ticks: { display: false }
        },
        x: {
          grid: { display: false },
          ticks: { color: themeColors.mutedForeground }
        }
      },
      plugins: {
        legend: {
          display: false,
        },
        tooltip: {
          enabled: false,
          position: 'nearest',
          external: externalTooltipHandler,
        }
      }
    }
  };

  new Chart(ctx, config);


  ctx = document.getElementById('chart-area-stacked');
  data = {
    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
    datasets: [{
      label: 'Desktop',
      data: [186, 305, 237, 73, 209, 214],
      borderWidth: 1,
      backgroundColor: setAlpha(themeColors.chart1, 0.2),
      borderColor: themeColors.chart1,
      pointRadius: 0,
      pointHoverRadius: 4,
      pointHoverBackgroundColor: themeColors.chart1,
      pointHoverBorderColor: themeColors.chart1,
      fill: 'origin'
    }, {
      label: 'Mobile',
      data: [80, 200, 120, 190, 130, 140],
      borderWidth: 1,
      backgroundColor: setAlpha(themeColors.chart2, 0.2),
      borderColor: themeColors.chart2,
      pointRadius: 0,
      pointHoverRadius: 4,
      pointHoverBackgroundColor: themeColors.chart2,
      pointHoverBorderColor: themeColors.chart2,
      fill: 'origin'
    }]
  };
  config = {
    type: 'line',
    data: data,
    options: {
      tension: 0.4,
      interaction: {
        mode: 'nearest',
        axis: 'x',
        intersect: false
      },
      scales: {
        y: {
          border: { display: false },
          grid: { 
            color: setAlpha(themeColors.border, 0.5),
            lineWidth: 1
          },
          ticks: { display: false }
        },
        x: {
          grid: { display: false },
          ticks: { color: themeColors.mutedForeground }
        }
      },
      plugins: {
        legend: {
          display: false,
        },
        tooltip: {
          enabled: false,
          position: 'nearest',
          external: externalTooltipHandler,
        }
      }
    }
  };

  new Chart(ctx, config);


  ctx = document.getElementById('chart-bar-multiple');
  data = {
    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
    datasets: [{
        label: 'Desktop',
        data: [186, 305, 237, 73, 209, 214],
        backgroundColor: themeColors.chart1,
        borderWidth: 0,
        borderRadius: 4,
        barPercentage: 0.7,
        categoryPercentage: 0.8
      }, {
        label: 'Mobile',
        data: [80, 200, 120, 190, 130, 140],
        backgroundColor: themeColors.chart2,
        borderWidth: 0,
        borderRadius: 4,
        barPercentage: 0.7,
        categoryPercentage: 0.8
      }]
  };

  config = {
    type: 'bar',
    data: data,
    options: {
      interaction: {
        mode: 'index',
        axis: 'x',
        intersect: false
      },
      scales: {
        y: {
          border: { display: false },
          grid: { 
            color: setAlpha(themeColors.border, 0.5),
            lineWidth: 1
          },
          ticks: { display: false }
        },
        x: {
          grid: { display: false },
          ticks: { color: themeColors.mutedForeground }
        }
      },
      plugins: {
        legend: {
          display: false,
        },
        tooltip: {
          enabled: false,
          position: 'nearest',
          external: externalTooltipHandler,
        }
      }
    }
  };

  new Chart(ctx, config);

  const chartData = [
  { date: "2024-04-01", desktop: 222, mobile: 150 },
  { date: "2024-04-02", desktop: 97, mobile: 180 },
  { date: "2024-04-03", desktop: 167, mobile: 120 },
  { date: "2024-04-04", desktop: 242, mobile: 260 },
  { date: "2024-04-05", desktop: 373, mobile: 290 },
  { date: "2024-04-06", desktop: 301, mobile: 340 },
  { date: "2024-04-07", desktop: 245, mobile: 180 },
  { date: "2024-04-08", desktop: 409, mobile: 320 },
  { date: "2024-04-09", desktop: 59, mobile: 110 },
  { date: "2024-04-10", desktop: 261, mobile: 190 },
  { date: "2024-04-11", desktop: 327, mobile: 350 },
  { date: "2024-04-12", desktop: 292, mobile: 210 },
  { date: "2024-04-13", desktop: 342, mobile: 380 },
  { date: "2024-04-14", desktop: 137, mobile: 220 },
  { date: "2024-04-15", desktop: 120, mobile: 170 },
  { date: "2024-04-16", desktop: 138, mobile: 190 },
  { date: "2024-04-17", desktop: 446, mobile: 360 },
  { date: "2024-04-18", desktop: 364, mobile: 410 },
  { date: "2024-04-19", desktop: 243, mobile: 180 },
  { date: "2024-04-20", desktop: 89, mobile: 150 },
  { date: "2024-04-21", desktop: 137, mobile: 200 },
  { date: "2024-04-22", desktop: 224, mobile: 170 },
  { date: "2024-04-23", desktop: 138, mobile: 230 },
  { date: "2024-04-24", desktop: 387, mobile: 290 },
  { date: "2024-04-25", desktop: 215, mobile: 250 },
  { date: "2024-04-26", desktop: 75, mobile: 130 },
  { date: "2024-04-27", desktop: 383, mobile: 420 },
  { date: "2024-04-28", desktop: 122, mobile: 180 },
  { date: "2024-04-29", desktop: 315, mobile: 240 },
  { date: "2024-04-30", desktop: 454, mobile: 380 },
  { date: "2024-05-01", desktop: 165, mobile: 220 },
  { date: "2024-05-02", desktop: 293, mobile: 310 },
  { date: "2024-05-03", desktop: 247, mobile: 190 },
  { date: "2024-05-04", desktop: 385, mobile: 420 },
  { date: "2024-05-05", desktop: 481, mobile: 390 },
  { date: "2024-05-06", desktop: 498, mobile: 520 },
  { date: "2024-05-07", desktop: 388, mobile: 300 },
  { date: "2024-05-08", desktop: 149, mobile: 210 },
  { date: "2024-05-09", desktop: 227, mobile: 180 },
  { date: "2024-05-10", desktop: 293, mobile: 330 },
  { date: "2024-05-11", desktop: 335, mobile: 270 },
  { date: "2024-05-12", desktop: 197, mobile: 240 },
  { date: "2024-05-13", desktop: 197, mobile: 160 },
  { date: "2024-05-14", desktop: 448, mobile: 490 },
  { date: "2024-05-15", desktop: 473, mobile: 380 },
  { date: "2024-05-16", desktop: 338, mobile: 400 },
  { date: "2024-05-17", desktop: 499, mobile: 420 },
  { date: "2024-05-18", desktop: 315, mobile: 350 },
  { date: "2024-05-19", desktop: 235, mobile: 180 },
  { date: "2024-05-20", desktop: 177, mobile: 230 },
  { date: "2024-05-21", desktop: 82, mobile: 140 },
  { date: "2024-05-22", desktop: 81, mobile: 120 },
  { date: "2024-05-23", desktop: 252, mobile: 290 },
  { date: "2024-05-24", desktop: 294, mobile: 220 },
  { date: "2024-05-25", desktop: 201, mobile: 250 },
  { date: "2024-05-26", desktop: 213, mobile: 170 },
  { date: "2024-05-27", desktop: 420, mobile: 460 },
  { date: "2024-05-28", desktop: 233, mobile: 190 },
  { date: "2024-05-29", desktop: 78, mobile: 130 },
  { date: "2024-05-30", desktop: 340, mobile: 280 },
  { date: "2024-05-31", desktop: 178, mobile: 230 },
  { date: "2024-06-01", desktop: 178, mobile: 200 },
  { date: "2024-06-02", desktop: 470, mobile: 410 },
  { date: "2024-06-03", desktop: 103, mobile: 160 },
  { date: "2024-06-04", desktop: 439, mobile: 380 },
  { date: "2024-06-05", desktop: 88, mobile: 140 },
  { date: "2024-06-06", desktop: 294, mobile: 250 },
  { date: "2024-06-07", desktop: 323, mobile: 370 },
  { date: "2024-06-08", desktop: 385, mobile: 320 },
  { date: "2024-06-09", desktop: 438, mobile: 480 },
  { date: "2024-06-10", desktop: 155, mobile: 200 },
  { date: "2024-06-11", desktop: 92, mobile: 150 },
  { date: "2024-06-12", desktop: 492, mobile: 420 },
  { date: "2024-06-13", desktop: 81, mobile: 130 },
  { date: "2024-06-14", desktop: 426, mobile: 380 },
  { date: "2024-06-15", desktop: 307, mobile: 350 },
  { date: "2024-06-16", desktop: 371, mobile: 310 },
  { date: "2024-06-17", desktop: 475, mobile: 520 },
  { date: "2024-06-18", desktop: 107, mobile: 170 },
  { date: "2024-06-19", desktop: 341, mobile: 290 },
  { date: "2024-06-20", desktop: 408, mobile: 450 },
  { date: "2024-06-21", desktop: 169, mobile: 210 },
  { date: "2024-06-22", desktop: 317, mobile: 270 },
  { date: "2024-06-23", desktop: 480, mobile: 530 },
  { date: "2024-06-24", desktop: 132, mobile: 180 },
  { date: "2024-06-25", desktop: 141, mobile: 190 },
  { date: "2024-06-26", desktop: 434, mobile: 380 },
  { date: "2024-06-27", desktop: 448, mobile: 490 },
  { date: "2024-06-28", desktop: 149, mobile: 200 },
  { date: "2024-06-29", desktop: 103, mobile: 160 },
  { date: "2024-06-30", desktop: 446, mobile: 400 },
]


data = {
  labels: chartData.map(d => d.date),
  datasets: [{
      label: 'Desktop',
      data: chartData.map(d => d.desktop),
      backgroundColor: themeColors.chart2,
      borderWidth: 0,
      borderRadius: 0, // Stacking usually looks better without individual radius
    }, {
      label: 'Mobile',
      data: chartData.map(d => d.mobile),
      backgroundColor: themeColors.chart1,
      borderWidth: 0,
      borderRadius: 0, // Stacking usually looks better without individual radius
    }]
};

ctx = document.getElementById('chart-bar-interactive');

// Restore helper function to format date for labels/tooltips
const formatDateLabel = (dateString) => {
  try {
    const date = new Date(dateString + 'T00:00:00');
    return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); // e.g., "Apr 1"
  } catch (event) {
    return dateString; // Fallback
  }
};

// Restore data preparation with formatted date labels
data = {
  labels: chartData.map(d => formatDateLabel(d.date)),
  datasets: [{
      label: 'Desktop',
      data: chartData.map(d => d.desktop),
      backgroundColor: themeColors.chart4,
      borderWidth: 0,
      borderRadius: 0,
    }, {
      label: 'Mobile',
      data: chartData.map(d => d.mobile),
      backgroundColor: themeColors.chart5,
      borderWidth: 0,
      borderRadius: 0,
    }]
};

config = {
  type: 'bar',
  data: data,
  options: {
    interaction: {
      mode: 'index',
      axis: 'x',
      intersect: false
    },
    scales: {
      y: {
        stacked: true,
        border: { display: false },
        grid: { 
          color: setAlpha(themeColors.border, 0.5),
          lineWidth: 1
        },
        ticks: { display: false }
      },
      x: {
        stacked: true,
        grid: { display: false },
        ticks: { 
          color: themeColors.mutedForeground,
          callback: function(value, index, ticks) {
            const label = this.getLabelForValue(value);
            return index % 7 === 0 ? label : null;
          },
          maxRotation: 0,
          minRotation: 0
        }
      }
    },
    plugins: {
      legend: {
        display: false,
      },
      tooltip: {
        enabled: false,
        position: 'nearest',
        external: externalTooltipHandler,
      }
    }
  }
};

new Chart(ctx, config);

// Same chart but with line chart
// We start off from the previous config and just change the type to line

ctx = document.getElementById('chart-line-interactive');

  
// Prepare data with formatted date labels AND offset for Mobile
const desktopData = chartData.map(d => d.desktop + 400); // Store raw desktop data
const mobileDataOffset = chartData.map(d => d.mobile); // Store offset mobile data

// Prepare data with gradient background
data = {
  labels: chartData.map(d => formatDateLabel(d.date)),
  datasets: [{
      label: 'Desktop',
      data: desktopData, 
      borderColor: themeColors.chart1,
      // Make backgroundColor scriptable
      backgroundColor: function(context) { 
        const chart = context.chart;
        const { ctx, chartArea } = chart;
        // Use the helper function defined above
        return createGradient(ctx, chartArea, themeColors.chart1);
      },
      borderWidth: 1,
      pointRadius: 0,
      pointHoverRadius: 4,
      pointHoverBackgroundColor: themeColors.chart1,
      pointHoverBorderColor: themeColors.chart1,
      fill: 'start' // Fill from the start (usually y=0 or axis baseline)
    }, {
      label: 'Mobile (Offset)', // Adjusted label
      data: mobileDataOffset, 
      borderColor: themeColors.chart2,
      // Make backgroundColor scriptable
      backgroundColor: function(context) {
        const chart = context.chart;
        const { ctx, chartArea } = chart;
        // Use the helper function defined above
        return createGradient(ctx, chartArea, themeColors.chart2);
      },
      borderWidth: 1,
      pointRadius: 0,
      pointHoverRadius: 4,
      pointHoverBackgroundColor: themeColors.chart2,
      pointHoverBorderColor: themeColors.chart2,
      fill: 'start' 
    }]
};

// Add the createGradient helper function before the data object
function createGradient(ctx, chartArea, color) {
  if (!chartArea) {
    return setAlpha(color, 0.1); // Fallback during initial setup
  }
  const gradient = ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
  gradient.addColorStop(0, setAlpha(color, 0.5)); // Start color at top
  gradient.addColorStop(1, setAlpha(color, 0));   // End color (transparent) at bottom
  return gradient;
}

// Calculate min/max for Y-axis scaling using the PLOTTED data
const allPlottedValues = [...desktopData, ...mobileDataOffset]; // Combine actual plotted values
const dataMin = Math.min(...allPlottedValues);
const dataMax = Math.max(...allPlottedValues);
const yPadding = (dataMax - dataMin) * 0.1; // Add 10% padding

config = {
  type: 'line',
  data: data,
  options: {
    maintainAspectRatio: false,
    aspectRatio: 1,
    tension: 0.4, // Keep tension from original line config
    interaction: {
      mode: 'index', // Use 'index' mode for better hover on multiple lines
      axis: 'x',
      intersect: false
    },
    scales: {
      y: {
        border: { display: false },
        grid: { 
          color: setAlpha(themeColors.border, 0.5),
          lineWidth: 1
        },
        ticks: { display: false },
        // Set min and max for Y-axis
        min: Math.max(0, dataMin - yPadding), // Ensure min is not negative
        max: dataMax + yPadding
      },
      x: {
        grid: { display: false },
        ticks: { 
          color: themeColors.mutedForeground,
          // Restore callback to reduce ticks
          callback: function(value, index, ticks) {
            const label = this.getLabelForValue(value);
            return index % 7 === 0 ? label : null;
          },
          maxRotation: 0,
          minRotation: 0
        }
      }
    },
    plugins: {
      legend: { display: false },
      tooltip: {
        enabled: false,
        position: 'nearest',
        external: externalTooltipHandler,
      }
    }
  }
};
    

new Chart(ctx, config);


const chartDataDoughnut = [
  { browser: "chrome", visitors: 275, fill: themeColors.chart1 }, // Use resolved colors
  { browser: "safari", visitors: 200, fill: themeColors.chart2 },
  { browser: "firefox", visitors: 287, fill: themeColors.chart3 },
  { browser: "edge", visitors: 173, fill: themeColors.chart4 },
  { browser: "other", visitors: 190, fill: themeColors.chart5 },
]

// Prepare data for the doughnut chart
const doughnutData = {
  labels: chartDataDoughnut.map(d => d.browser),
  datasets: [{
    label: 'Visitors by Browser',
    data: chartDataDoughnut.map(d => d.visitors),
    backgroundColor: chartDataDoughnut.map(d => d.fill),
    borderColor: themeColors.background, // Use background for border
    borderWidth: 0, // Add border between segments
    hoverBorderColor: themeColors.background,
    hoverBorderWidth: 0
  }]
};

// Configure the doughnut chart
const doughnutConfig = {
  type: 'doughnut',
  data: doughnutData,
  options: {
    cutout: '70%', // Adjust hole size
    plugins: {
      legend: {
        display: false, // Hide default legend
      },
      tooltip: {
        enabled: false, // Keep this false as we use external handler
        position: 'nearest', // Keep this for external handler logic
        external: externalTooltipHandler, // Use the existing handler
      },
      centerText: {} // Keep the custom plugin for center text
    }
  }
};

// Assume you have a canvas with id="chart-doughnut" in your HTML
const doughnutCtx = document.getElementById('chart-doughnut').getContext('2d');
new Chart(doughnutCtx, doughnutConfig);
</script>